#pragma once

#define THIS_FILE_NAME		"fay.exe"

#include "text.h"
#include "control.h"
#include "sound.h"

#include <Ogre.h>
#include <SdkTrays.h>
#include <Terrain\OgreTerrainGroup.h>


size_t max(size_t a, size_t b);

const Ogre::Vector3 CAM_OFFSET = Ogre::Vector3(0, 50, 300);

class Base:
	public Ogre::FrameListener,
	public Ogre::WindowEventListener,
	public OIS::KeyListener,
	public OIS::MouseListener,
	public OgreBites::SdkTrayListener
{
private:
	// ogre functional root
	Ogre::Root* root;

	// main window handle
	Ogre::RenderWindow* window;

	// ogre scene manager
	Ogre::SceneManager* scene_manager;

	// game text system
	TextMap text_map;

	// game controler class defined in control.cpp
	Controler controler;

	// 2D UI
	Ogre::Viewport* viewport;
	Ogre::Camera* cam;
	OgreBites::SdkTrayManager* tray_manager;
	
	// terrain
	Ogre::TerrainGlobalOptions* terrain_option;
	Ogre::TerrainGroup* terrain_group;


	// load game cfg
	bool load_cfg();

	// update input event, <F> = FPS label, <Escape> = Exit dialog
	bool work_basic(Ogre::Real time);

	// start loading the game world, this take time, but is done in parallel
	bool load_world();

	// load resources.cfg
	void prepare_res();

	// game status (important for scene and game)
	// commands are passing using FLAG
	enum BASE_FLAG
	{
		BASE_MAINTAIN = 0,
		BASE_EXIT,
		BASE_OPEN,
		BASE_SELECT,
		BASE_HELP,
		BASE_PAUSE,
		BASE_START,
		BASE_RESET,
		BASE_GAME_NORMAL,
		BASE_GAME_PRO
	};

	// last_flag stores the last flag that is not MAINTAIN or PAUSE
	BASE_FLAG flag, last_flag;
	bool cfg_changed, first_run;

	// Sound engine
	Sounder sounder;

	// The selected camera or keyboard name
	Ogre::String cam_selected;

protected:
	// window event
	virtual void windowResized(Ogre::RenderWindow* rw);
	virtual void windowClosed(Ogre::RenderWindow* rw);
	
	// frame event
	virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);

	// OIS event
	// OIS::KeyListener
	virtual bool keyPressed(const OIS::KeyEvent &arg);
	virtual bool keyReleased(const OIS::KeyEvent &arg);
	// OIS::MouseListener
	virtual bool mouseMoved(const OIS::MouseEvent &arg);
	virtual bool mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id);
	virtual bool mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id);

	// SDKTray event
	virtual void buttonHit(OgreBites::Button* button);
	virtual void itemSelected(OgreBites::SelectMenu* menu);
	virtual void labelHit(OgreBites::Label* label);
	virtual void sliderMoved(OgreBites::Slider* slider);
	virtual void checkBoxToggled(OgreBites::CheckBox* box);
	virtual void okDialogClosed(const Ogre::DisplayString& message);
	virtual void yesNoDialogClosed(const Ogre::DisplayString& question, bool yesHit);

public:
	Base();
	~Base();
	
	Sounder* get_sounder();
	Ogre::Camera* get_cam();

	bool init();
	bool reinit();
	void main();
	Ogre::RenderWindow* get_window();
	
	// scenes to draw
	void open_scene(bool destroy = false);
	void select_scene(bool destroy = false);
	void help_scene(bool destroy = false);
	void start_scene(bool destroy = false);
	

	// work with restarting problems
	char* get_restart_param();
	void work_exec_param(Ogre::String params);
	void get_focus();
	void check_pos();

	// get mapped text
	Ogre::String get_text(Ogre::String key);
	Ogre::DisplayString get_UTFtext(Ogre::String key);
};
